(function($) {

    function _buildTextField(element) {
        element.html('<label>' +
                     '    <span>' + element.attr('label') + ': </span>' +
                     '    <input type="text" name="' + element.attr('name') + '" value="' + (element.attr('value') || '') + '"/>' +
                     '</label>')
    }

    var _buildField = {
        text: _buildTextField,
        password: function(element) {
            element.html('<label>' +
                         '    <span>' + element.attr('label') + ': </span>' +
                         '    <input type="password" name="' + element.attr('name') + '" value="' + (element.attr('value') || '') + '"/>' +
                         '</label>')
        }
    };

    /////////////////////////////////////////////////////////////

    var Form = function(selector) {
        this.form = $(selector);
        this.initComponents();
    };

    Form.prototype.validate = function() {
        return true;
    };

    Form.prototype.initComponents = function() {
        var f = this;

        this.form.find('.ext-form-field').each(function() {
            f.buildField($(this));
        });
    };

    Form.prototype.buildField = function(element) {
        var type = element.attr('type');
        _buildField[type](element);
    };

    Form.prototype.find = function(selector) {
        return this.form.find(selector);
    };

    Form.prototype.serialize = function() {
        return this.form.serialize();
    };

    Form.prototype.val = function(name, value) {
        var form = this.form.get(0);

        // get value
        if (value === undefined) {
            for (var i = 0; i < form.elements.length; i++) {
                if (name == form.elements[i].name) {
                    return form.elements[i].value;
                }
            }
            return null;
        }

        // set value
        if ($.isArray(value)) {
            $(form).find('[name=' + name + ']').remove();
            for (var i = 0; i < value.length; i++) {
                $(form).append($('<input type="hidden" name="' + name + '" value="' + value[i] + '"/>'));
            }
        } else {
            value = value == null? '': value;
            var element = form[name];
            if (!element) {
                $(form).append('<input type="hidden" name="' + name + '" value=""/>');
            }

            element = form[name];
            if (element) {
                if (element.tagName == 'INPUT') {
                    if (element.getAttribute('type') == 'text' ||
                        element.getAttribute('type') == 'password' ||
                        element.getAttribute('type') == 'hidden') {
                        element.value = value;
                    } else if (element.getAttribute('type') == 'checkbox' ||
                               element.getAttribute('type') == 'radio') {
                        if (element.value == value) {
                            element.checked = true;
                        }
                    }
                } else if (element.tagName == 'SELECT') {
                    for (var i = 0; i < element.options.length; i++) {
                        if (element.options[i].value == value) {
                            element.selectedIndex = i;
                        }
                    }
                }
            }
        }

        return this;
    };

    Form.prototype.clear = function() {
        this.form.find('input:text,input:password,input:hidden').val('');
        this.form.find('select').each(function() {
            this.selectedIndex = 0;
        });
        this.form.find('input:checkbox,input:radio').each(function() {
            this.checked = false;
        });

        return this;
    };

    Form.prototype.read = function(properties, exceptPropertyNames) {
        for (var name in properties) {
            if (exceptPropertyNames == undefined || exceptPropertyNames.indexOf(name) == -1) {
                this.val(name, properties[name]);
            }
        }

        return this;
    };

    Form.prototype.extend = function(value) {
        var result = {};
        var form = this.form.get(0);
        for (var i = 0; i < form.elements.length; i++) {
            result[form.elements[i].name] = form.elements[i].value;
        }
        return value === undefined? result: $.extend(value, result);
    };

    Form.prototype.isEmpty = function(name) {
        var form = this.form.get(0);
        if (!form.elements[name]) {
            return true;
        }

        var value = form.elements[name].value;
        return value === undefined || value == null || value == "" || value.match(/^\s+$/);
    };

    Form.prototype.notEmpty = function(name) {
        return !this.isEmpty(name);
    };

    $.form = function(selector, options) {
        var f = $(selector);
        if (f.size() == 0) {
            throw "Form '" + selector + "' doesn't exist."
        }

        return $.extend(new Form(f), options);
    };



})(jQuery);